%% @author Mochi Media <dev@mochimedia.com>
%% @copyright 2010 Mochi Media <dev@mochimedia.com>

%% @doc Web server for mochiweb_ttim.

-module(mochiweb_ttim_web).
-author("Mochi Media <dev@mochimedia.com>").

-export([start/1, stop/0, loop/2]).

%% External API

start(Options) ->
    {DocRoot, Options1} = get_option(docroot, Options),
    Loop = fun (Req) ->
                   ?MODULE:loop(Req, DocRoot)
           end,
    mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).

stop() ->
    mochiweb_http:stop(?MODULE).

loop(Req, DocRoot) ->
    "/http-bind/" ++ Path = Req:get(path),
    try
        case Req:get(method) of
            Method when Method =:= 'GET'; Method =:= 'HEAD' ->
                case Path of
   		     "conn" ->
 			Data = Req:parse_qs(),
                        Id = proplists:get_value("uid", Data),
                        Pwd = proplists:get_value("pwd", Data),
			Sid = proplists:get_value("sid", Data),
                        User = {Sid, Id, Pwd}, 
			router:login(User, self()),
			feed(Req, Id); 	
		     _ ->
                        Req:serve_file(Path, DocRoot)
                end;
            'POST' ->
                case Path of
                    "conn" ->
                        Data = Req:parse_post(), 
                        Id = proplists:get_value("uid", Data),
                        Pwd = proplists:get_value("pwd", Data),
                        Sid = proplists:get_value("sid", Data),  
                       % Response = Req :ok ( { "text/plain; charset=utf-8" ,
                        %              [ { "Server" ,"Mochiweb-TTIM" } ] ,
                         %             chunked} ) , 
                        User={Sid, Id, Pwd},
                        router:login(User, self()),
                        feed(Req, Id);
                    "sendmsg" ->
                        Data = Req:parse_post(), 
                        From = proplists:get_value("from", Data), 
                        To = proplists:get_value("to", Data),
                        Body = proplists:get_value("body", Data),
			router:send(To,From, Body),
                        Req:respond({200, [{"Content-Type", "text/plain"}],
                                     "Hello " ++ From ++ "!\n"});
                    "getpresence" ->
                        Data = Req:parse_post(), 
                        From = proplists:get_value("from", Data), 
                        Body = proplists:get_value("body", Data),
			Struct = mochijson2:decode(Body),
                        Fuids = struct:get_value(<<"fuids">>, Struct),
			router:get_presence(From, Fuids),
                        Req:respond({200, [{"Content-Type", "text/plain"}],
                                     "Hello " ++ From ++ "!\n"});
                    _ ->
                        Req:not_found()
                end;
            _ ->
                Req:respond({501, [], []})
        end
    catch
        Type:What ->
            Report = ["web request failed",
                      {path, Path},
                      {type, Type}, {what, What},
                      {trace, erlang:get_stacktrace()}],
            error_logger:error_report(Report),
            %% NOTE: mustache templates need \ because they are not awesome.
            Req:respond({500, [{"Content-Type", "text/plain"}],
                         "request failed, sorry\n"})
    end.

feed(Req, Id) ->
    receive
	{connected, Msg} ->
            DataOut = mochijson2:encode(Msg),
            Req:ok({"application/json",[],[DataOut]});
        {new_msg, Msg} ->
	    %Html = io_lib:format("Recvd msg : '~s'<br/>", [Msg]),
	    %Req:respond({200, [{"Content-Type", "text/plain"}],Html});   
            io:format("new_msg: ~p ~n", [Msg]),
            DataOut = mochijson2:encode(Msg),
            Req:ok({"application/json",[],[DataOut]});
        {get_presence, Msg} ->
            DataOut = mochijson2:encode(Msg),
            Req:ok({"application/json",[],[DataOut]});
	{router_presence, Msg} ->
            DataOut = mochijson2:encode(Msg),
            Req:ok({"application/json",[],[DataOut]});
        {failed_conn, Msg} ->
	    Req:respond({200, [{"Content-Type", "text/plain"}],Msg})   	    			  
    after 10000 ->
        Msg = {struct, [{<<"ns">>,<<"conn">>}, {<<"result">>, <<"keep-alive">>}]},
        DataOut = mochijson2:encode(Msg),
        Req:ok({"application/json",[],[DataOut]})
	%Req:respond({200, [{"Content-Type", "text/plain"}],Msg})
    end.
    %feed(Req, Id).

%% Internal API

get_option(Option, Options) ->
    {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.

%%
%% Tests
%%
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

you_should_write_a_test() ->
    ?assertEqual(
       "No, but I will!",
       "Have you written any tests?"),
    ok.

-endif.
